package com.tywj.panda.customer.common.widget.calendar

import android.content.Context
import android.graphics.Color
import android.text.TextUtils
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.*
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.BaseQuickAdapter.OnItemClickListener
import com.chad.library.adapter.base.BaseViewHolder
import com.tywj.lib.core.common.extension.onClick
import com.tywj.lib.core.common.util.ResourcesUtil
import com.tywj.lib.core.common.util.ToastUtil
import com.tywj.panda.customer.common.R
import com.tywj.panda.customer.common.entity.CalendarPriceEntity
import com.tywj.panda.customer.common.event.PriceEvent
import com.tywj.panda.customer.common.tool.DateUtil
import com.tywj.panda.customer.common.tool.MoneyTool
import com.tywj.panda.customer.common.tool.TimeTool
import java.util.*
import kotlin.collections.ArrayList

/**
 * <pre>
 *     author : June Yang
 *     time   : 2020/05/23
 *     desc   : 日历控件（针对下单）
 *     思路：手机端先生成静态日历，再从服务器返回的数据进行比对，再进行数据填充
 *     version: 2.0.0
 * </pre>
 */
@Suppress("DEPRECATION")
class CalendarView : LinearLayout {

    companion object {

        const val FOR_MATE_YMD = "yyyy-MM-dd"
    }

    //相关属性
    private var titleColor = 0
    private var titleSize = 0
    private var enableSelectColor = 0
    private var disableSelectColor = 0
    private var todayColor = 0
    private var todayEmptyColor = 0
    private var todayFillColor = 0

    //上一个月
    private lateinit var ivPreMonth: ImageView

    //下一个月
    private lateinit var ivNextMonth: ImageView

    //标题
    private lateinit var title: TextView


    private lateinit var rvCalendar: RecyclerView
    private lateinit var linearLayoutManager: LinearLayoutManager

    //获取当前时间 转换为格式为 2020-06-05
    private var curDate = Calendar.getInstance()

    //从服务器获取的日期
    private var dateFromServer: CalendarPriceEntity? = null

    //外层主recyclerview的adapter
    private lateinit var mainAdapter: MainRvAdapter

    //子adapter
    private var subRvAdapter: SubRvAdapter? = null

    private val months: MutableList<CalendarCell> = ArrayList()

    private var scrollDx = 0 // 记录X轴当前滑动的的位置
    private var currentPage = 0 // 当前页


    //卡片第一个月
    private var firstMonth = -1 //卡片第一个月（中间）
    private var secondMonth = -1 //卡片第二个月（中间）
    private var thirdMonth = -1 //卡片第三个月（中间）

    private val titles: MutableList<String> = ArrayList()


    private val priceHashMap = HashMap<Int, ArrayList<CalendarPriceEntity>>()

    private lateinit var snapHelper: SnapHelper


    constructor(context: Context) : this(context, null, 0)

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        initAttr(context, attrs)
    }

    private fun initAttr(context: Context, attrs: AttributeSet?) {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.MyCalendar)
        titleColor = ta.getColor(R.styleable.MyCalendar_titleColor, ResourcesUtil.getColor(R.color.common_black_33))
        titleSize = ta.getDimension(R.styleable.MyCalendar_titleSize, 18f).toInt()
        enableSelectColor = ta.getColor(
            R.styleable.MyCalendar_dayInMonthColor,
            ResourcesUtil.getColor(R.color.common_black_33)
        )
        disableSelectColor = ta.getColor(
            R.styleable.MyCalendar_dayOutMonthcolor,
            ResourcesUtil.getColor(R.color.common_gray_CC)
        )
        todayColor =
            ta.getColor(R.styleable.MyCalendar_todayColor, Color.RED)

        todayEmptyColor = ta.getColor(
            R.styleable.MyCalendar_todayEmptycircleColor,
            Color.CYAN
        )
        todayFillColor = ta.getColor(
            R.styleable.MyCalendar_todayFillcircleColor,
            Color.CYAN
        )
        ta.recycle()

        init(context)
    }

    //该方法用于设置从服务器获取的时间，如果没有从服务器获取的时间将使用手机本地时间
    private fun initTime(time: String = "") {
        dateFromServer = CalendarPriceEntity()

        if (TextUtils.isEmpty(time)) {
            curDate = Calendar.getInstance()

        } else {
            curDate = DateUtil.strToCalendar(time, FOR_MATE_YMD)

            val date = DateUtil.strToDate(time, FOR_MATE_YMD)
            dateFromServer?.date = date
        }
    }

    //如果数据为空，日历如何显示
    fun init(context: Context) {
        bindView(context)
    }

    private fun bindView(context: Context) {
        val view = LayoutInflater.from(context).inflate(R.layout.common_appoint_calendarview, this, false)
        title = view.findViewById(R.id.calendarTitle)

        title.setTextColor(titleColor)
        title.textSize = titleSize.toFloat()

        ivPreMonth = view.findViewById(R.id.ivPreMonth)
        ivNextMonth = view.findViewById(R.id.ivNextMonth)

        rvCalendar = view.findViewById(R.id.rvCalendar)

        linearLayoutManager = LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false)
        rvCalendar.layoutManager = linearLayoutManager

        //横向滑动时一页一页滑动
        snapHelper = PagerSnapHelper()

        snapHelper.attachToRecyclerView(rvCalendar)

        addView(view)
    }

    //服务器数据填充
    private fun loadServerCalendar(dateList: ArrayList<CalendarPriceEntity>) {
        months.clear()

        currentPage = 0 // 当前页恢复默认值
        priceHashMap.clear() //缓存的价格置为空

        initTime(dateList.first().lineDate)

        for (i in 0..2) {
            //遍历月份
            val cells = ArrayList<CalendarPriceEntity>()

            if (i != 0) {
                curDate.add(Calendar.MONTH, 1) //后退一个月
            } else {
                curDate.add(Calendar.MONTH, 0) //当前月
            }

            val calendar = curDate.clone() as Calendar

            //将日历设置到当月第一天
            calendar[Calendar.DAY_OF_MONTH] = 1

            //获得当月第一天是星期几，如果是星期一则返回1此时1-1=0 证明上个月没有多余天数
            val prevDays = calendar[Calendar.DAY_OF_WEEK] - 1

            //将calendar在1号的基础上向前推 prevdays天。
            calendar.add(Calendar.DAY_OF_MONTH, -prevDays)

            // 一般情况下都是5*7行就可以足够显示本月跟非半月日期，但是当1号恰好是周六的时候，显示就需要6*7行了，也因此我我们需要判断这个月的1号是星期几，算出多余了上月几天
            val maxCellCount = 6 * 7

            while (cells.size < maxCellCount) {
                //判断当前时间是否和服务器返回的时间相同
                var bean = CalendarPriceEntity()

                val index = isSameDayByIndex(calendar, dateList)

                if (index != -1) {
                    //有排班可点击
                    bean = dateList[index]
                    bean.isSaleStatus = true
                    bean.isCanBuy = bean.storeNum > 0
                } else {
                    //没有排班只有日期不可点击
                    bean.isSaleStatus = false
                    bean.isCanBuy = false
                }

                bean.date = calendar.time

                cells.add(bean)
                //日期后移一天
                calendar.add(Calendar.DAY_OF_MONTH, 1) //当前天往后移一天
            }

            //按月生成 对应月的日历
            months.add(CalendarCell(i, cells))
        }
        firstMonth = dateFromServer!!.date.month //第一个月

        secondMonth = months[1].cells[20].date.month //第二个月

        thirdMonth = months[2].cells[20].date.month //第三个月


        for (i in months.indices) {
            //title格式 2018年6月3日
            val title = (months[i].cells[20].date.year + 1900).toString() +
                    context.resources.getString(R.string.year) +
                    (months[i].cells[20].date.month + 1) + context.resources
                .getString(R.string.month)

            titles.add(title)
        }
        title.text = titles[0]

        //只限定3个月，因此模拟给3个数值即可
        mainAdapter = MainRvAdapter(R.layout.common_appoint_calendarview_item, months)

        rvCalendar.adapter = mainAdapter

        initListener()
    }

    //生成静态数据
    private fun renderCalendar(time: String = "") {
        months.clear()
        initTime(time)

        //遍历月份
        for (i in 0..2) {

            val cells = ArrayList<CalendarPriceEntity>()

            if (i != 0) {
                curDate.add(Calendar.MONTH, 1) //后退一个月
            } else {
                curDate.add(Calendar.MONTH, 0) //当前月
            }

            val calendar = curDate.clone() as Calendar

            //将日历设置到当月第一天
            calendar[Calendar.DAY_OF_MONTH] = 1

            //获得当月第一天是星期几，如果是星期一则返回1此时1-1=0证明上个月没有多余天数
            val prevDays = calendar[Calendar.DAY_OF_WEEK] - 1

            //将calendar在1号的基础上向前推prevdays天。
            calendar.add(Calendar.DAY_OF_MONTH, -prevDays)
            // 一般情况下都是5*7行就可以足够显示本月跟非半月日期，但是当1号恰好是周六的时候，显示就需要6*7行了，也因此我我们需要判断这个月的1号是星期几，算出多余了上月几天
            val maxCellCount = 6 * 7

            while (cells.size < maxCellCount) {
                val bean = CalendarPriceEntity()
                bean.date = calendar.time
                cells.add(bean)
                //日期后移一天
                calendar.add(Calendar.DAY_OF_MONTH, 1)
            }

            //按月生成 对应月的日历
            months.add(CalendarCell(i, cells))
        }


        firstMonth = dateFromServer!!.date.month //第一个月

        secondMonth = months[1].cells[20].date.month //第二个月

        thirdMonth = months[2].cells[20].date.month //第三个月


        for (i in months.indices) {
            //title格式 2018年6月3日
            val title = (months[i].cells[20].date.year + 1900).toString() +
                    context.resources.getString(R.string.year) +
                    (months[i].cells[20].date.month + 1) + context.resources
                .getString(R.string.month)

            titles.add(title)
        }
        title.text = titles[0]

        //只限定3个月，因此模拟给3个数值即可
        mainAdapter = MainRvAdapter(R.layout.common_appoint_calendarview_item, months)

        rvCalendar.adapter = mainAdapter

        initListener()
    }

    private fun initListener() {
        //recyclerview 的滚动监听
        rvCalendar.addOnScrollListener(object : RecyclerViewPageChangeListenerHelper(snapHelper,
            object : OnPageChangeListener {
                override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) {
                    title.text = titles[linearLayoutManager.findLastVisibleItemPosition()]
                }

                //监听手势滑动的距离
                override fun onScrolled(recyclerView: RecyclerView?, dx: Int, dy: Int) {
                    scrollDx += dx
                }

                //监听当前第几页
                override fun onPageSelected(position: Int) {
                    currentPage = position

                    listener?.selectedCurrent(currentPage)
                }
            }) {

        })

        //上一月
        ivPreMonth.onClick {
            if (currentPage == 0) {
                rvCalendar.smoothScrollBy(0, 0)
                ToastUtil.shortToast("已到最早支持的购票月份")
            } else {
                rvCalendar.smoothScrollBy(-rvCalendar.width, 0)
            }
        }
        //下一月
        ivNextMonth.onClick {

            if (currentPage == 0) {
                rvCalendar.smoothScrollBy(rvCalendar.width, 0)
            } else if (currentPage == 1) {
                rvCalendar.smoothScrollBy(2 * rvCalendar.width, 0)
            } else {
                ToastUtil.shortToast("已到最晚支持的购票月份")
            }
        }
    }


    /**
     * 最外层水平recyclerview的adapter
     */
    private inner class MainRvAdapter internal constructor(layoutResId: Int, data: List<CalendarCell>?) :
        BaseQuickAdapter<CalendarCell, BaseViewHolder>(layoutResId, data) {

        override fun convert(helper: BaseViewHolder, item: CalendarCell) {

            val rvCalenderView = helper.getView<RecyclerView>(R.id.appointCalendarView)

            if (rvCalenderView.layoutManager == null) {
                //RecyclerView不能都使用同一个LayoutManager
                val manager = GridLayoutManager(mContext, 7)
                //recyclerview嵌套高度不固定（wrap_content）时必须setAutoMeasureEnabled(true)，否则测量时控件高度为0
                manager.isAutoMeasureEnabled = true
                rvCalenderView.layoutManager = manager
            }
            //时间切换时 注意缓存 待优化
            subRvAdapter = SubRvAdapter(R.layout.common_calendar_text_day_item, item.cells)

            rvCalenderView.adapter = subRvAdapter
            //第几页第几个
            subRvAdapter?.onItemClickListener = OnItemClickListener { _, _, position ->
                val bean = item.cells[position]

//                LogUtil.d("当前页：" + item.position)  // 0、1、2
//                LogUtil.d("当前票价信息：$bean")

                if (!bean.isCanBuy) {
                    return@OnItemClickListener
                }
                if (isCanChoose(bean)) {
                    bean.isSelected = !bean.isSelected
                    notifyDataSetChanged()

                    val list = item.cells.filter { it.isSelected } as ArrayList<CalendarPriceEntity>
                    priceHashMap[item.position] = list

                    PriceEvent.getSelectedPriceList.post(priceHashMap)
                }
            }
        }
    }

    //里面的子项 adapter
    private inner class SubRvAdapter(layoutResId: Int, data: List<CalendarPriceEntity>?) :
        BaseQuickAdapter<CalendarPriceEntity, BaseViewHolder>(layoutResId, data) {

        override fun convert(helper: BaseViewHolder, bean: CalendarPriceEntity) {
            //不让recyclerview进行复用，复用会出问题
//            helper.setIsRecyclable(false)
            val day = bean.date
            helper.setText(R.id.tvCalendarDay, day.date.toString())
            //设置颜色
            if (isCanChoose(bean)) {
                //可选时间
                helper.getView<TextView>(R.id.tvCalendarDay).setTextColor(enableSelectColor)

                //检查是否售罄
                if (bean.isCanBuy) {
                    helper.getView<LinearLayout>(R.id.calendarDayll)
                        .setBackgroundColor(ResourcesUtil.getColor(R.color.common_transparent))

                    helper.getView<LinearLayout>(R.id.calendarDayll).background =
                        ResourcesUtil.getDrawable(R.drawable.common_bg_rect_white_stroke_1)

                    helper.setText(R.id.tvTicketPrice, MoneyTool.formatFen(bean.sellPrice))

                    helper.getView<TextView>(R.id.tvTicketPrice)
                        .setTextColor(ResourcesUtil.getColor(R.color.common_red_FF))

                    //是否选择
                    if (bean.isSelected) {
                        helper.getView<LinearLayout>(R.id.calendarDayll)
                            .setBackgroundColor(ResourcesUtil.getColor(R.color.common_yellow_FD))
                    } else {
                        helper.getView<LinearLayout>(R.id.calendarDayll)
                            .setBackgroundColor(ResourcesUtil.getColor(R.color.common_white))
                    }

                } else {
                    //售罄
                    helper.getView<LinearLayout>(R.id.calendarDayll)
                        .setBackgroundColor(ResourcesUtil.getColor(R.color.common_gray_DA))

                    helper.setText(R.id.tvTicketPrice, "售罄")

                    if (bean.sellNum == 0) {
                        helper.setText(R.id.tvTicketPrice, "未排班")
                    }

                    helper.getView<TextView>(R.id.tvTicketPrice)
                        .setTextColor(ResourcesUtil.getColor(R.color.common_black_33))
                }

            } else {
                //不可选时间
                helper.getView<TextView>(R.id.tvCalendarDay).setTextColor(disableSelectColor)
                helper.getView<LinearLayout>(R.id.calendarDayll).background = null
            }

            //判断是否为当天
            if (TimeTool.isToDay(bean.date)) {
                helper.getView<TextView>(R.id.tvCalendarDay)
                    .setTextColor(ResourcesUtil.getColor(R.color.common_blue_16))
            }
        }
    }

    private inner class CalendarCell(var position: Int, var cells: ArrayList<CalendarPriceEntity>)

    /**
     * 根据时间是否可选
     */
    private fun isCanChoose(bean: CalendarPriceEntity): Boolean {
        return (bean.date.month == secondMonth
                || bean.date.date >= dateFromServer?.date!!.date && bean.date.month == firstMonth
                || bean.date.date <= dateFromServer?.date!!.date && bean.date.month == thirdMonth)
    }


    //判断服务器返回的数据和当前的日期是否为同一天
    private fun isSameDayByIndex(dateTime: Calendar, dataList: ArrayList<CalendarPriceEntity>): Int {

        //得到 格式类似于2020 04 31
        val year = dateTime.get(Calendar.YEAR).toString()
        val month =
            String.format(ResourcesUtil.getString(R.string.common_month), dateTime.get(Calendar.MONTH) + 1) //必须要+1
        val day = String.format(ResourcesUtil.getString(R.string.common_day), dateTime.get(Calendar.DATE))

        dataList.forEachIndexed { index, calendarPriceEntity ->
            val strYearMonthDay = calendarPriceEntity.lineDate.split("-")
            //如果机同返回当前对象
            if (year == strYearMonthDay[0] && month == strYearMonthDay[1] && day == strYearMonthDay[2]) {
                return index
            }
        }
        return -1
    }


    //1.服务器数据加载进来
    fun loadDatePrice(context: Context, dateList: ArrayList<CalendarPriceEntity>) {
        loadServerCalendar(dateList)
    }


    private var listener: ISelectedAll? = null

    //当前页全选 42个数据中包含两个月或三个月的数据  由0、1、2来区分
    interface ISelectedAll {
        fun selectedCurrent(position: Int)
    }

    fun selectedCurrentAll(mListener: ISelectedAll) {
        this.listener = mListener
    }
}